package br.com.medmark.model.hibernate.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;


public class GenericoDAOImpl<T> implements GenericDAO<T>, Serializable{
	
	private static final long serialVersionUID = -5922521126535250715L;

	private final Class<T>	persistentClass;
	
	protected EntityManager entityManager = Persistence.createEntityManagerFactory("med_mark").createEntityManager();
	
	@SuppressWarnings("unchecked")
	public GenericoDAOImpl() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0];
	}

	@Override
	public void save(T obj) throws SQLException {
		try{
			this.entityManager.getTransaction().begin();
			this.entityManager.merge(obj);
			this.entityManager.flush();
			//T toReturn = this.entityManager.merge(obj);
			this.entityManager.getTransaction().commit();
		}catch(Throwable e){
			throw new SQLException(e);
		}
	}
	
	@Override
	public T update(T obj) throws SQLException {
		try{
			this.entityManager.getTransaction().begin();
			T toReturn = this.entityManager.merge(obj);
			this.entityManager.getTransaction().commit();
			return toReturn;
		}catch(Throwable e){
			throw new SQLException(e);
		}
	}

	@Override
	public void delete(T obj) throws SQLException {
		try{
			this.entityManager.getTransaction().begin();
			if (obj != null) {
				this.entityManager.remove(obj);
			}
			this.entityManager.getTransaction().commit();
		}catch(Throwable e){
			throw new SQLException(e);
		}
	}

	@Override
	public void deleteFromList(T[] list) throws SQLException {
		try{
			this.entityManager.getTransaction().begin();
			for (T obj : list) {
				if (obj != null) {
					this.entityManager.remove(obj);
				}
			}
			this.entityManager.getTransaction().commit();
		}catch(Throwable e){
			throw new SQLException(e);
		}
		
	}

	@Override
	public List<T> listarObjetos() {
		CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
		CriteriaQuery<T> query = criteriaBuilder.createQuery(persistentClass);
		Root<T> root = query.from(persistentClass);
		query.select(root);

		return this.entityManager.createQuery( query ).getResultList();
	}

	@Override
	public T localizaObjeto(Long objId) {
		CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
		CriteriaQuery<T> query = criteriaBuilder.createQuery(persistentClass);
		Root<T> root = query.from(persistentClass);
		query.select(root);

		query.where( criteriaBuilder.equal( root.get( "id" ), objId ) );

		return this.entityManager.createQuery( query ).getSingleResult();
	}


}
